package me.szlx.thing;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

public interface Trait extends TraitLet {
    /**
     * 获取特性名称。总返回一个不为{@code null}的字符串。
     *
     * @return 特性代码。
     */
    String getName();

    /**
     * 获取特性值，特性值可能为{@code null}。
     *
     * @return 特性值。
     */
    String getValue();

    /**
     * 将特征件整理为独个的特征数组。如果没有任何特征件，则返回空的数组。
     *
     * @param traitLets 待整理的特征件。
     * @return 整理的独个特征数组。
     */
    static Trait[] marshal(TraitLet... traitLets) {
        List<Trait> traitList = new ArrayList<>();
        if (traitLets != null) {
            for (TraitLet traitLet : traitLets) {
                if (traitLet != null) {
                    if (traitLet instanceof Trait) {
                        traitList.add((Trait) traitLet);
                    } else { // Type
                        Iterator<Trait> tagIterator = ((Traits) traitLet).iterator();
                        while (tagIterator.hasNext()) {
                            Trait theTrait = tagIterator.next();
                            if (theTrait != null) {
                                traitList.add(theTrait);
                            }
                        }
                    }
                }
            }
        }
        return traitList.toArray(new Trait[0]);
    }

    /**
     * <p>
     * 判断是否匹配指定的标签。如果匹配则返回{@code true}，否则返回{@code false}。
     * </p>
     * <p>
     * 如果指定的标签为{@code null}，则总是返回{@code true}，表示实际上无需进行任何匹配。
     * </p>
     *
     * @param trait  待匹配的标签。
     * @param action 匹配行为。
     * @return 匹配则返回{@code true}，否则返回{@code false}。
     */
    default boolean match(Trait trait, MatchAction action) {
        if (trait == null) {
            return true;
        }
        action = action != null ? action : MatchAction.NAME_AND_VALUE;
        if (MatchAction.NAME_AND_VALUE.equals(action)) {
            return this.equals(trait);
        } else if (MatchAction.NAME_ONLY.equals(action)) {
            return getName().equals(trait.getName());
        }
        throw new ThingException("不支持的标签匹配操作符");
    }

    static Trait create(String name, String value) {
        return new TraitVO(name, value);
    }

    static Trait create(String name) {
        return new TraitVO(name);
    }

    /**
     * 标签皮匹配行为。
     */
    enum MatchAction {
        NAME_ONLY, NAME_AND_VALUE;
    }
}

class TraitVO implements Trait {
    private String name;
    private String value;

    public TraitVO(String name, String value) {
        this.name = Objects.requireNonNull(name, "特性名称不能为null");
        this.value = value;
    }

    public TraitVO(String name) {
        this(name, null);
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getValue() {
        return value;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Trait)) return false;

        Trait vo = (Trait) o;

        if (name != null ? !name.equals(vo.getName()) : vo.getName() != null) return false;
        return value.equals(vo.getValue());
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + value.hashCode();
        return result;
    }
}